package com.wondream.myframework.app.common.aspect;

import com.wondream.myframework.app.common.annotation.DecryptAnno;
import com.wondream.myframework.app.common.exception.BusinessException;
import com.wondream.myframework.app.common.exception.BusinessExeceptionCode;
import com.wondream.myframework.app.common.util.FieldUtils;
import com.wondream.myframework.app.common.util.SpringUtils;
import com.wondream.myframework.app.vo.base.OpRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.joda.time.DateTime;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 订单号解密处理
 */
@Aspect
@Component
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
public class AesDecryptAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(public * com.wondream.myframework.app.controller.web..*.*(..))")
    public void pointCut(){

    }

    /**
     * 拦截要执行的目标方法
     */
    @Around("pointCut()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        String op = "AesDecryptAspect.aroundAdvice";
        long startTimestamp = System.currentTimeMillis();
        // 非接口不拦截
        log.info("开始切面解密");
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        Method method = ms.getMethod();
        log.info("method:"+method.getName());
        Object[] arguments = pjp.getArgs();
        Type[] types = method.getGenericParameterTypes();
        Type type = types[0];
        if (type instanceof ParameterizedType) {
            Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments();
            Type actualType = actualTypes[0];
            log.info("开始解密");
            Object arg = arguments[0];
            OpRequest opRequest = (OpRequest) arg;
            Class cls = (Class) actualType;
            ReflectionUtils.doWithFields(cls,f -> {
                DecryptAnno decryptAnno = f.getAnnotation(DecryptAnno.class);
                if(decryptAnno == null){
                    return;
                }
                try {
                    Method getMethod = cls.getMethod(FieldUtils.getGetMethodName(f.getName()));
                    Object value = getMethod.invoke(opRequest.getParams());
                    if(value == null || StringUtils.isBlank(value.toString())){
                        return;
                    }
                    Method setMethod = cls.getMethod(FieldUtils.getSetMethodName(f.getName()), String.class);
                    setMethod.invoke(opRequest.getParams(), SpringUtils.getBean(decryptAnno.clz()).decrypt(value.toString()));
                } catch (Exception e) {
                    log.error(e.getMessage());
                    throw BusinessExeceptionCode.SYS_ERROR.exp();
                }
            });
        }
        return pjp.proceed();
    }
}
